var Options = function () {
    this.eyeX = 0.5;
    this.eyeY = 0;
    this.eyeZ = 2.5;
    this.centerX = 0;
    this.centerY = 0;
    this.centerZ = 0;
    this.upX = 0;
    this.upY = 1;
    this.upZ = 0;

    this.left = -1;
    this.right = 1;
    this.bottom = -1;
    this.top = 1;
    this.near = 0.1;
    this.far = 100;

    this.fovy = 30;
    this.aspect = 1;
};

const gui = new dat.GUI();
var options = new Options();

gui.add(options, 'eyeX', -1, 1).step(0.01);
gui.add(options, 'eyeY', -1, 1).step(0.01);
gui.add(options, 'eyeZ', -1, 5).step(0.01);
gui.add(options, 'centerX', -1, 1).step(0.01);
gui.add(options, 'centerY', -1, 1).step(0.01);
gui.add(options, 'centerZ', -10, 1).step(0.01);
gui.add(options, 'upX', -1, 1).step(0.01);
gui.add(options, 'upY', -1, 1).step(0.01);
gui.add(options, 'upZ', -1, 1).step(0.01);

gui.add(options, 'left', -10, 10).step(0.01);
gui.add(options, 'right', -10, 10).step(0.01);
gui.add(options, 'bottom', -10, 10).step(0.01);
gui.add(options, 'top', -10, 10).step(0.01);
gui.add(options, 'near', -10, 10).step(0.01);
gui.add(options, 'far', -10, 100).step(1);
gui.add(options, 'fovy', -10, 100).step(1);
gui.add(options, 'aspect', -10, 10).step(0.01);

// let forwrad_abs_listen = gui.add(options, 'forwrad_abs').step(0.01).listen();
// let fx_listen = gui.add(options, 'fx').step(0.01).listen();
// let fy_listen = gui.add(options, 'fy').step(0.01).listen();
// let fz_listen = gui.add(options, 'fz').step(0.01).listen();

var VSHADER_SOURCE =
    'attribute vec4 a_Position;\n' +
    'attribute vec4 a_Color;\n' +
    'uniform mat4 u_ViewMatrix;\n' +
    'uniform mat4 u_ProjMatrix;\n' +
    'varying vec4 v_Color;\n' +
    'void main() {\n' +
    '  gl_Position = u_ProjMatrix * u_ViewMatrix * a_Position;\n' +
    '  v_Color = a_Color;\n' +
    '}\n';

var FSHADER_SOURCE =
    '#ifdef GL_ES\n' +
    'precision mediump float;\n' +
    '#endif\n' +
    'varying vec4 v_Color;\n' +
    'void main() {\n' +
    '  gl_FragColor = v_Color;\n' +
    '}\n';

function lookAtTriangles() {
    var canvas = document.getElementById('webgl');

    var gl = getWebGLContext(canvas);

    gl.getExtension("EXT_frag_depth");

    if(gl.getSupportedExtensions().indexOf("EXT_frag_depth") < 0) {
        console.log('Failed to get the EXT_frag_depth');
        return;
    }

    if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
    }

    if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        console.log('Failed to intialize shaders.');
        return;
    }

    var n = initVertexBuffers(gl);
    if (n < 0) {
        console.log('Failed to set the vertex information');
        return;
    }

    // gl.clearColor(0, 0, 0, 1);

    var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');
    if (!u_ViewMatrix) {
        console.log('Failed to get the storage locations of u_ViewMatrix');
        return;
    }

    var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');
    if (!u_ProjMatrix) {
        console.log('Failed to get the storage locations of u_ProjMatrix');
        return;
    }

    // var u_far = gl.getUniformLocation(gl.program, 'u_far');
    // if (!u_far) {
    //     console.log('Failed to get the storage locations of u_far');
    //     return;
    // }


    gl.clearColor(0, 0, 0, 1);

    gl.enable(gl.DEPTH_TEST);
    gl.enable(gl.POLYGON_OFFSET_FILL);
    gl.enable(gl.POLYGON_OFFSET_FACTOR);
    gl.enable(gl.POLYGON_OFFSET_UNITS);

    function draw() {
        //==============================================================================

        let eyeX = options.eyeX;
        let eyeY = options.eyeY;
        let eyeZ = options.eyeZ;
        let centerX = options.centerX;
        let centerY = options.centerY;
        let centerZ = options.centerZ;
        let upX = options.upX;
        let upY = options.upY;
        let upZ = options.upZ;

        let left = options.left;
        let right = options.right;
        let bottom = options.bottom;
        let top = options.top;
        let near = options.near;
        let far = options.far;

        let fovy = options.fovy;
        let aspect = options.aspect;

        //===================================实图矩阵===========================================
        var viewMatrix = new Float32Array([
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1
        ]);

        var e = viewMatrix;
        e[0] = 1;e[4] = 0;e[8] = 0;e[12] = 0;
        e[1] = 0;e[5] = 1;e[9] = 0;e[13] = 0;
        e[2] = 0;e[6] = 0;e[10] = 1;e[14] = 0;
        e[3] = 0;e[7] = 0;e[11] = 0;e[15] = 1;

        /**
         *  叉乘分量公式
         *  Cx = Ay*Bz - Az*By;
         *  Cy = Az*Bx - Ax*Bz;
         *  Cz = Ax*By - Ay*Bx;
         */

            // let nX = eyeX - centerX;
            // let nY = eyeY - centerY;
            // let nZ = eyeZ - centerZ;

        let nX = centerX - eyeX;
        let nY = centerY - eyeY;
        let nZ = centerZ - eyeZ;

        let rln = Math.sqrt(nX * nX + nY * nY + nZ * nZ);
        nX = nX/rln;
        nY = nY/rln;
        nZ = nZ/rln;

        let uX = nY*upZ - nZ*upY;
        let uY = nZ*upX - nX*upZ;
        let uZ = nX*upY - nY*upX;

        let rlu = Math.sqrt(uX * uX + uY * uY + uZ * uZ);
        uX = uX/rlu;
        uY = uY/rlu;
        uZ = uZ/rlu;

        let vX = nY*uZ - nZ*uY;
        let vY = nZ*uX - nX*uZ;
        let vZ = nX*uY - nY*uX;

        // e[0] = uX;  e[4] = vX;  e[8] = nX;  e[12] = 0;
        // e[1] = uY;  e[5] = vY;  e[9] = nY;  e[13] = 0;
        // e[2] = uZ;  e[6] = vZ;  e[10] = nZ; e[14] = 0;
        // e[3] = 0;   e[7] = 0;   e[11] = 0;  e[15] = 1;

        e[0] = uX;  e[4] = uY;  e[8] = uZ;  e[12] = 0;
        e[1] = vX;  e[5] = vY;  e[9] = vZ;  e[13] = 0;
        e[2] = -nX;  e[6] = -nY;  e[10] = -nZ; e[14] = 0;
        e[3] = 0;   e[7] = 0;   e[11] = 0;  e[15] = 1;

        e[12] += e[0] * -eyeX + e[4] * -eyeY + e[8]  * -eyeZ;
        e[13] += e[1] * -eyeX + e[5] * -eyeY + e[9]  * -eyeZ;
        e[14] += e[2] * -eyeX + e[6] * -eyeY + e[10] * -eyeZ;

        e[15] += e[3] * -eyeX + e[7] * -eyeY + e[11] * -eyeZ;

        //==================================投影矩阵============================================

        var projMatrix = new Float32Array([
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1
        ]);

        var o = projMatrix;

        // let rw = 1 / (right - left);
        // let rh = 1 / (top - bottom);
        // let rd = 1 / (far - near);
        // o[0]  = 2 * rw; o[4]  = 0;      o[8]  = 0;      o[12] = -(right + left) * rw;
        // o[1]  = 0;      o[5]  = 2 * rh; o[9]  = 0;      o[13] = -(top + bottom) * rh;
        // o[2]  = 0;      o[6]  = 0;      o[10] = -2 * rd;o[14] = -(far + near) * rd;
        // o[3]  = 0;      o[7]  = 0;      o[11] = 0;      o[15] = 1;

        var rd, s, ct;
        fovy = Math.PI * fovy / 180 / 2;
        s = Math.sin(fovy);

        rd = 1 / (far - near);
        ct = Math.cos(fovy) / s;
        o[0]  = ct / aspect;    o[4]  = 0;  o[8]  = 0;                  o[12] = 0;
        o[1]  = 0;              o[5]  = ct; o[9]  = 0;                  o[13] = 0;
        o[2]  = 0;              o[6]  = 0;  o[10] = -(far + near) * rd; o[14] = -2 * near * far * rd;
        o[3]  = 0;              o[7]  = 0;  o[11] = -1;                 o[15] = 0;

        gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix);
        gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix);

        // gl.clear(gl.COLOR_BUFFER_BIT);

        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        gl.drawArrays(gl.TRIANGLES, 0, n/3);
        gl.polygonOffset(1.0, 1.0);
        gl.drawArrays(gl.TRIANGLES, n/3, n/3);
        gl.drawArrays(gl.TRIANGLES, 2 * n/3, n/3);
    }

    function step(timestamp) {
        draw();
        window.requestAnimationFrame(step);
    }
    requestAnimationFrame(step)

}


function initVertexBuffers(gl) {
    var verticesColors = new Float32Array([
        0.0,  0.5,   0.0,  0.4,  0.4,  1.0,  // The front blue one
        -0.5, -0.5,   0.0,  0.4,  0.4,  1.0,
        0.5, -0.5,   0.0,  1.0,  0.4,  0.4,

        0.5,  0.4,  0.0,  1.0,  0.4,  0.4, // The middle yellow one
        -0.5,  0.4,  0.0,  1.0,  1.0,  0.4,
        0.0, -0.6,  0.0,  1.0,  1.0,  0.4,

        0.0,  0.5,  -2,  0.4,  1.0,  0.4, // The back green one
        -0.5, -0.5,  -2,  0.4,  1.0,  0.4,
        0.5, -0.5,  -2,  1.0,  0.4,  0.4,

        // 0.0,  2.5,  -5.0,  0.4,  1.0,  0.4, // The green triangle
        // -2.5, -2.5,  -5.0,  0.4,  1.0,  0.4,
        // 2.5, -2.5,  -5.0,  1.0,  0.4,  0.4,
        //
        // 0.0,  3.0,  -5.0,  1.0,  0.4,  0.4, // The yellow triagle
        // -3.0, -3.0,  -5.0,  1.0,  1.0,  0.4,
        // 3.0, -3.0,  -5.0,  1.0,  1.0,  0.4,
    ]);
    var n = 9;

    var vertexColorbuffer = gl.createBuffer();
    if (!vertexColorbuffer) {
        console.log('Failed to create the buffer object');
        return -1;
    }

    gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);
    gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);

    var FSIZE = verticesColors.BYTES_PER_ELEMENT;

    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    if (a_Position < 0) {
        console.log('Failed to get the storage location of a_Position');
        return -1;
    }
    gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 6, 0);
    gl.enableVertexAttribArray(a_Position);

    var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
    if (a_Color < 0) {
        console.log('Failed to get the storage location of a_Color');
        return -1;
    }
    gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);
    gl.enableVertexAttribArray(a_Color);

    gl.bindBuffer(gl.ARRAY_BUFFER, null);

    return n;
}


lookAtTriangles()


